{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.append(\"../\")\n",
    "\n",
    "from typing import Callable, Tuple\n",
    "from fppy.gt import S, T, GenericTypeVar\n",
    "\n",
    "VoidCallable = Callable[[], S]\n",
    "\n",
    "def lazy_cons(head: VoidCallable[S], tail: VoidCallable[S] | Tuple):\n",
    "    \"\"\"基于二元元组的LazyList\n",
    "    \"\"\"\n",
    "    return (head, tail)\n",
    "\n",
    "def make_lazy_cons(*args: S) -> VoidCallable[S]:\n",
    "    if len(args) == 0:\n",
    "        return ()\n",
    "    else:\n",
    "        return lazy_cons(lambda: args[0], lambda: make_lazy_cons(*args[1:]))\n",
    "\n",
    "head = lambda lls: lls[0]()\n",
    "tail = lambda lls: lls[1]()\n",
    "\n",
    "def iterate_lazy_cons(start: S):\n",
    "    def helper(f: Callable[[S], S]):\n",
    "        return lazy_cons(\n",
    "            lambda: start, \n",
    "            lambda: iterate_lazy_cons(f(start))(f)\n",
    "        )\n",
    "    return helper\n",
    "\n",
    "def filter_lazy_cons(f: Callable[[S], bool]):\n",
    "    def helper(lls):\n",
    "        if lls == ():\n",
    "            return ()\n",
    "        else:\n",
    "            return lazy_cons(\n",
    "                lambda : head(lls) if head(lls) != () and f(head(lls)) else (),\n",
    "                lambda : filter_lazy_cons(f)(tail(lls))\n",
    "            )\n",
    "    return helper\n",
    "\n",
    "def collect_lazy_cons(lls):\n",
    "    if lls == ():\n",
    "        return ()\n",
    "    elif head(lls) == ():\n",
    "        return collect_lazy_cons(tail(lls))\n",
    "    else:\n",
    "        return (head(lls), collect_lazy_cons(tail(lls)))\n",
    "\n",
    "def take_lazy_cons(n: int):\n",
    "    def helper(lls):\n",
    "        if n == 0:\n",
    "            return ()\n",
    "        elif head(lls) == ():\n",
    "            return take_lazy_cons(n)(tail(lls))\n",
    "        else:\n",
    "            return (head(lls), take_lazy_cons(n - 1)(tail(lls)))\n",
    "    return helper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = iterate_lazy_cons(1)(lambda x: x + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, (2, (3, ())))"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "take_lazy_cons(3)(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = make_lazy_cons(1, 2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, (3, ()))"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "collect_lazy_cons(filter_lazy_cons(lambda x: x % 2 == 1)(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, (2, ()))"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "take_lazy_cons(2)(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, (2, (3, ())))"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "collect_lazy_cons(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [],
   "source": [
    "def map_lazy_cons(f):\n",
    "    def helper(lls):\n",
    "        if lls == ():\n",
    "            return ()\n",
    "        if head(lls) == ():\n",
    "            return lazy_cons(\n",
    "                lambda: (),\n",
    "                lambda: map_lazy_cons(f)(tail(lls))\n",
    "            )\n",
    "        else:\n",
    "            return lazy_cons(\n",
    "                lambda: f(head(lls)),\n",
    "                lambda: map_lazy_cons(f)(tail(lls))\n",
    "            )\n",
    "    return helper"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, (3, (4, (5, ()))))"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "take_lazy_cons(4)(map_lazy_cons(lambda x: x+ 1)(a))"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "b00d0533784e0bd7ec39dc1f12727fcf9021e9a985583666278f4fb55e7dfcf4"
  },
  "kernelspec": {
   "display_name": "Python 3.10.0 64-bit ('fppy2': conda)",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
